﻿using Cofe.Core.Filter;
using Cofe.Core.Implements;
using Cofe.Core.Interfaces;
using Cofe.Core.Property;
using Cofe.Core.Utils;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Cofe.Core
{
    public static class ICofeDirectoryInfoExtension
    {

        #region EnumerateFSIs, GetFSIsAsync

        private static IEntryFilter[] checkRootEntryFilter(this ICofeDirectoryInfo container, IEntryFilter[] entryFilters)
        {
            if (!(entryFilters.Any((f) => f is RootEntryFilter)))
            {
                var f = new List<IEntryFilter>(entryFilters);
                f.Add(new RootEntryFilter(container.Properties));
                entryFilters = f.ToArray();
            }
            return entryFilters;
        }


        public static IEnumerable<ICofeSystemInfo> EnumerateCofeSystemInfos(this ICofeDirectoryInfo container,
             EntryConstructionFlags flags = EntryConstructionFlags.Default)
        {
            return EnumerateCofeSystemInfos(container, new IEntryFilter[] { }, new IOptionFilter[] { },
                flags, CofeServices.EntryConstructor);
        }

        public static async Task<IEnumerable<ICofeSystemInfo>> GetCofeSystemInfosAsync(this ICofeDirectoryInfo container,
           EntryConstructionFlags flags = EntryConstructionFlags.Default)           
        {
            return await GetCofeSystemInfosAsync(container, new IEntryFilter[] { }, new IOptionFilter[] { },
                flags, CofeServices.EntryConstructor);
        }


        [EditorBrowsable(EditorBrowsableState.Never)]
        public static IEnumerable<ICofeSystemInfo> EnumerateCofeSystemInfos(this ICofeDirectoryInfo container,           
           FilterCollections filterCollection,
           EntryConstructionFlags flags = EntryConstructionFlags.Default, IEntryConstructor entryConstructor = null
           )
        {
            if (entryConstructor == null) entryConstructor = CofeServices.EntryConstructor;
            IEntryFilter[] entryFilters = checkRootEntryFilter(container, filterCollection.EntryFilters);
            IOptionFilter[] optionFilters = filterCollection.OptionFilters;
            bool enableCache = flags.HasFlag(EntryConstructionFlags.EnableCache);

            var entryList = container.Properties
             .Behaviors.Invoke<IEnumerable<ICofeSystemInfo>>(CofeDirectoryProperties.List,
             new ParameterDic { { "EntryFilters", entryFilters }, { "OptionFilters", optionFilters }, { "EnableCache", enableCache } });

            return entryList;
        }

        [EditorBrowsable(EditorBrowsableState.Never)]
        public static IEnumerable<ICofeSystemInfo> EnumerateCofeSystemInfos(this ICofeDirectoryInfo container,
           IEntryFilter[] entryFilters, IOptionFilter[] optionFilters,
           EntryConstructionFlags flags, IEntryConstructor entryConstructor
           )
        {
            return EnumerateCofeSystemInfos(container, FilterCollections.FromFilters(entryFilters, optionFilters), flags, entryConstructor);
        }

        [EditorBrowsable(EditorBrowsableState.Never)]
        public static async Task<IEnumerable<ICofeSystemInfo>> GetCofeSystemInfosAsync(this ICofeDirectoryInfo container,
           FilterCollections filterCollection,
           EntryConstructionFlags flags = EntryConstructionFlags.Default,
           IEntryConstructor entryConstructor = null
           )
        {
            if (entryConstructor == null) entryConstructor = CofeServices.EntryConstructor;
            IEntryFilter[] entryFilters = checkRootEntryFilter(container, filterCollection.EntryFilters);
            IOptionFilter[] optionFilters = filterCollection.OptionFilters;
            var enableCache = flags.HasFlag(EntryConstructionFlags.EnableCache);
            var entryList = (await container.Properties
              .Behaviors.InvokeAsync<IEnumerable<ICofeSystemInfo>>(CofeDirectoryProperties.ListAsync,
              new ParameterDic { { "EntryFilters", entryFilters }, { "OptionFilters", optionFilters }, { "EnableCache", enableCache } }))
              .ToList();

            return entryList;
        }

        [EditorBrowsable(EditorBrowsableState.Never)]
        public static Task<IEnumerable<ICofeSystemInfo>> GetCofeSystemInfosAsync(this ICofeDirectoryInfo container,           
           IEntryFilter[] entryFilters, IOptionFilter[] optionFilters,
           EntryConstructionFlags flags,
           IEntryConstructor entryConstructor = null)
        {
            return GetCofeSystemInfosAsync(container, FilterCollections.FromFilters(entryFilters, optionFilters), flags, entryConstructor);
        }

        #endregion

        #region CreateAsync

        [EditorBrowsable(EditorBrowsableState.Never)]
        public static async Task<ICofeSystemInfo> CreateAsync(this ICofeDirectoryInfo container, string type, string name)
        {
            ParameterDic pd = new ParameterDic() { { "Name" , name }, { "Type", type } };
            return await container.Properties.CreateAsync(pd, CofeServices.EntryConstructor);
        }

        [EditorBrowsable(EditorBrowsableState.Never)]
        public static async Task<T> CreateAsync<T>(this ICofeDirectoryInfo directoryInfo, string type, string name)
            where T : ICofeSystemInfo
        {
            return (await directoryInfo.CreateAsync(type, name)).As<T>();
        }

        [EditorBrowsable(EditorBrowsableState.Never)]
        public static async Task<ICofeDirectoryInfo> CreateCofeDirectoryAsync(this ICofeDirectoryInfo directoryInfo, string name)
        {
            return await directoryInfo.CreateAsync<ICofeDirectoryInfo>("directory", name);
        }


        #endregion

    }
}
